## matplotlibScatterplot.  An interactive scatterplot made using matplotlib.  Should allow for curve selection and identify 

"""
<name>Matplotlib Scatterplot</name>
<author>Written by Kyle R. Covington</author>
<description>A plotting widget that creates a scatterplot given a rectangular data set, for example the RDataFrame or StructuredDict signals.</description>
<RFunctions>None</RFunctions>
<tags>Matplotlib Plotting</tags>
<icon>icons/plot.png</icon>
"""
from OWRpy import * 
import redRGUI
import libraries.base.signalClasses.StructuredDict as std

class matplotlibScatterplot(OWRpy):
    def __init__(self, parent=None, signalManager=None):
        OWRpy.__init__(self)
        
        
        self.inputs.addInput('Data', 'Data', std.StructuredDict, self.gotData)
        self.outputs.addOutput('Data', 'Data', std.StructuredDict)
        
        ### GUI ###
        advancedArea = redRGUI.widgetBox(self.GUIDialog)
        
        # an area to select the columns of the plot data, these should be the names of the structuredDict that are not 'row_names'
        self.xCombo = redRGUI.comboBox(advancedArea, label = 'X Data', callback = self.plot)
        self.yCombo = redRGUI.comboBox(advancedArea, label = 'Y Data', callback = self.plot)
        self.colorCombo = redRGUI.comboBox(advancedArea, label = 'Color Data', callback = self.plot)
        self.sizeCombo = redRGUI.comboBox(advancedArea, label = 'Size Data', callback = self.plot)
        
        #self.legendArea = redRGUI.textEdit(advancedArea)
        
        self.selectionsArea = redRGUI.groupBox(advancedArea, label = 'Selection Area')
        self.selectionsArea.hide()
        self.selectionList = redRGUI.listBox(advancedArea, label = 'Selections')
        self.selectionList.setSelectionMode(QAbstractItemView.MultiSelection)
        redRGUI.button(self.selectionsArea, label = 'Send Selections', callback = self.sendSelections)
        self.selectButton = redRGUI.button(advancedArea, 'Select', callback = self.startSelection)
        button = redRGUI.button(advancedArea, 'Get Selected', callback = self.getSelectedPoints)
        
        self.myPlot = redRGUI.RedRmatplotlib.mplScatterplot(self.controlArea)
    def startSelection(self):
        
        
        if self.myPlot.interactionMode == 'None':
            ### set a color for the background
            colorDialog = QColorDialog(self)
            color = colorDialog.getColor()
            colorDialog.hide()
            print str(color.name())
            if str(color.name()) != '#000000':  # this happens when the cancel button is pressed.
                self.myPlot.workingColor = str(color.name())
            self.selectButton.setText('End Selection')
            self.myPlot.setSelectionMode(mode = True)
        else:
            
            self.selectButton.setText('Select')
            self.myPlot.setSelectionMode(mode = False)
    def gotData(self, data):
        if data:
            self.data = data
            xyNames = self.data.getData().keys()
            self.xCombo.update(xyNames)
            self.yCombo.update(xyNames)
            
            self.colorCombo.update([''] + xyNames)
            self.sizeCombo.update([''] + xyNames)
            self.plot()
        else:
            self.xCombo.clear()
            self.yCombo.clear()
            self.colorCombo.clear()
            self.sizeCombo.clear()
    def getSelectedPoints(self):
        print 'Gettings Selections'
        self.selectionCriteria = self.myPlot.getSelected()
        
        ### Send the data where the selections are true
        if len(self.selectionCriteria.keys()) > 1:
            self.selectionsArea.show()
            self.selectionList.update(self.selectionCriteria.keys())
        else:
            self.selectionsArea.hide()
            self.sendSelections(self.selectionCriteria.keys()[0])
            
    def sendSelections(self, key = None):
        print 'Getting Selections'
        print key
        if not key:
            trues = numpy.zeros(len(self.selectionCriteria.items()[0][1]))
            for i in self.selectionList.selectedItems():
                l = self.selectionCriteria[str(i.text())]
                print l, i.text()
                n = 0
                for li in l:
                    if li:
                        trues[n] = 1
                    n += 1
        else:
            trues = self.selectionCriteria[key]
        
        newDict = {}
        for name in self.data.getData().keys():
            newDict[name] = []
            for i in range(len(trues)):
                if trues[i]:
                    newDict[name].append(self.data.getData()[name][i])
                    
        print newDict, trues
        newData = std.StructuredDict(data = newDict, parent = self.data)
        self.rSend('Data', newData)
    def asNumeric(self, data):
        newData = []
        keyVals = {}
        intSpace = 0
        for i in data:
            try:
                newData.append(float(i))
            except:
                if i in keyVals.keys():
                    newData.append(keyVals[i])
                else:
                    keyVals[i] = intSpace
                    intSpace += 1
                    newData.append(keyVals[i])
        return newData
        
    def asColor(self, data):
        pass
    def plot(self):
        ### make the calls that will go to the plot to make the scatterplot.
        if not self.data or str(self.xCombo.currentText()) == '':
            return # there isn't any data
            
        x = self.asNumeric(self.data.getData()[str(self.xCombo.currentText())])
        y = self.asNumeric(self.data.getData()[str(self.yCombo.currentText())])
        if str(self.colorCombo.currentText()) != '':
            c = self.asNumeric(self.data.getData()[str(self.colorCombo.currentText())])
        else:
            c = 'b'
        if str(self.sizeCombo.currentText()) != '':
            s = self.asNumeric(self.data.getData()[str(self.sizeCombo.currentText())])
        else:
            s = 2
        self.myPlot.makePlot(x = x, y = y, s = s*10, c = c)
        
    